﻿using System;
using System.Collections.Generic;
using System.Linq;
using MenesDroid;
using MenesDroid.EngineCharacter;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using XNA_Game_Engine.Characters;
using XNA_Game_Engine.GUI;
using XNA_Game_Engine.Map;
using XNA_Game_Engine.Sounds;
using Buttons = XNA_Game_Engine.GUI.Buttons;

namespace XNA_Game_Engine.Canvas
{
    
    class GameCanvas : Canvas
    {
        private readonly LinkedList<Character> _objects;
        //private readonly Frame _frame;
        private LevelCompleteFrame levelCompleteFrame;
        private IsometricTilemap _map;
        private EventHandler _events;
        private bool jumping = false;
        private Enemy enemy;
        private String level;
        private Frame tipFrame;
        
        

        public GameCanvas(Game game, String level )
        {
            Width = game.Window.ClientBounds.Width;
            Height = game.Window.ClientBounds.Height;
            _objects = new LinkedList<Character>();
            Buttons = new Botoes();
            Rand = new Random();

            StaticGui.StaticGuiInit();

            Background = new Texture2D(game.GraphicsDevice,100,100);
            this.level = level;
           // _frame = new SettingsFrame(game, Width / 4, Height / 4, Width / 2, Height / 2);
            levelCompleteFrame = new LevelCompleteFrame( game, 100, 100, Width - 200, Height - 200 );
            CreateTipFrame();
        }


        public override void LoadContent(ContentManager Content)
        {
            #region Frame, Tileset, Map
           // _frame.LoadContent(Content);
            levelCompleteFrame.LoadContent(Content);

            var tileset = Content.Load<Texture2D>(@"Maps\tileset");
            _map = new IsometricTilemap(level, tileset);
            //_map = new IsometricTilemap( 65, 42, 10, 10, tileset );
            #endregion
            #region Player
            var robot = Content.Load<Texture2D>(@"Robot\robot2");
            var enemyImg = Content.Load<Texture2D>(@"Robot\enemy2");

            var arrowSprite = Content.Load<Texture2D>(@"Arrow");
            var enmyKillSprite = Content.Load<Texture2D>(@"Effects\enemyKill");
            var arrowExplosionSprite = Content.Load<Texture2D>(@"Effects\arrowExplosion");

            var sprite = new AnimatedSprite(robot, 1000, 1, 4);
            var enemySprite = new AnimatedSprite(enemyImg, 1000, 1, 4);
           
            var player = new Robot(0, 0, sprite, _map, enmyKillSprite);
            //enemy = new Enemy(2, 5, enemySprite, _map);

           

            _events = new EventHandler(player, enemy, _map, this); //Passando a criaçao do robo pra dentro da classe EventHandler
            _events.setSprites(enemySprite, arrowSprite, arrowExplosionSprite);
           
            
            _objects.AddLast(player);
           // _objects.AddLast(enemy);

            StaticGui.PlayerReference = player;

           
            SoundController.playSound("fase1");
          

            #endregion
            #region Load da interface e inicialização das Listas de comandos
            StaticGui.Font = Content.Load<SpriteFont>("font");
            StaticGui.OptionMenu.Bot.Add(new clsButton(Content.Load<Texture2D>(@"Buttons\Exit_phase_button"),
                                                           Content.Load<Texture2D>(@"Buttons\Exit_phase_button"),
                                                           new Vector2(Width/2 - 128, 300), new Vector2(255, 75),
                                                           ActionsHandler.StartButtonEvent));

            StaticGui.OptionMenu.Bot.Add(new clsButton(Content.Load<Texture2D>(@"Buttons\exit_button"),
                                                          Content.Load<Texture2D>(@"Buttons\exit_button"),
                                                          new Vector2(Width / 2 - 128, 400), new Vector2(255, 75),
                                                          ActionsHandler.ExitButtonEvent));

            //HashSet<String, Texture2D> texturas;
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandListNEW\slots")); //0
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandList\BotShortInventoryBar")); //1
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandList\RightInventoryBar")); //2
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandList\LeftInventoryBar")); //3
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandList\RightSlot")); //4
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandList\LeftSlot")); //5
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandListNEW\slots")); //6
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandListNEW\walk")); //7
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandList\SlotSetaAtras")); //8
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandListNEW\turn_left")); //9
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandListNEW\turn_right")); //10
            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandListNEW\jump")); //11

            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\play")); //12
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\play_deactived")); //13
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\play_deactived")); //14
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\pause")); //15
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\pause_deactived")); //16
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\pause_deactived")); //17
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\stop")); //18
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\stop_deactived")); //19
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\stop_deactived")); //20
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\function_1")); //21
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\function_2")); //22

            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\MainBar")); //23
            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\MainBarSelected")); //24

            StaticGui.Image.Add(Content.Load<Texture2D>(@"GUI-ButtonsNEW\eraseButton")); //25

            //Tooltips
            StaticGui.Image.Add(Content.Load<Texture2D>(@"tooltips\frente")); //26
            StaticGui.Image.Add(Content.Load<Texture2D>(@"tooltips\esquerda")); //27
            StaticGui.Image.Add(Content.Load<Texture2D>(@"tooltips\direita")); //28
            StaticGui.Image.Add(Content.Load<Texture2D>(@"tooltips\pulo")); //29

            StaticGui.Image.Add(Content.Load<Texture2D>(@"ComandListNEW\selected")); //30

            StaticGui.PlayButton = new Buttons(StaticGui.Image[12], StaticGui.Image[13], StaticGui.Image[14], new Rectangle(52, 10, StaticGui.slotsSize, StaticGui.slotsSize), true)
                                    {
                                        MouseReleased = () => StaticGui.TimeStart.Start()
                                    };
            StaticGui.StopButton = new Buttons(StaticGui.Image[18], StaticGui.Image[19], StaticGui.Image[20], new Rectangle(107, 10, StaticGui.slotsSize, StaticGui.slotsSize), false)
                                       {
                                           MouseReleased = () => StaticGui.TimeStart.Stop()
                                       };

            //Lista de Comandos a serem executados pelo jogador
            const int panelForCommandsPositionX = 25;
            int panelForCommandsPositionY = StaticGui.slotsSize + 50;
            const int panelForCommandsLinesCount = 5;
            const int panelForCommandsColumnsCount = 3;
            StaticGui.PanelForCommands = new GuiSlotList(panelForCommandsPositionX, panelForCommandsPositionY,
                                                         panelForCommandsLinesCount, panelForCommandsColumnsCount, null,
                                                         false);

            //clear Commands Button
            const int clearCommandsWidth = 125;
            int clearCommandsX = panelForCommandsPositionX - clearCommandsWidth/2 +
                                 (StaticGui.slotsSize*panelForCommandsColumnsCount/2);
            int clearCommandsY = panelForCommandsPositionY +
                                 (StaticGui.slotsSize*panelForCommandsLinesCount);
            Buttons.Add(new clsButton(StaticGui.Image[25], StaticGui.Image[25],
                                      new Vector2(clearCommandsX, clearCommandsY), new Vector2(125, 50),
                                      delegate { StaticGui.ClearButtons(); }));

            StaticGui.SelectedPanel = StaticGui.PanelForCommands;

            #region AvailableCommandsInterface
            int x = ( Width/2 ) - ( 2 * StaticGui.slotsSize ); //Centro dos comandos eh o centro da tela/  ( nmr de comandos/2 * tamanho do icone )
            int y = Height - 100;
            int w = StaticGui.slotsSize;
            int h = StaticGui.slotsSize;

            #region AvailableCommands
            StaticGui.AvailableCommands = new GuiSlotList(x, y, 1, 4, new List<GuiSlot>(), false);
            StaticGui.FunctionCommands = new GuiSlotList((Width - w*3) - 25, 50, 5, 3, null, true)
                                             {
                                                 IsVisible = ActionsHandler.level >= 5
                                             };

            var slots = new List<GuiSlot>
                            {
                                new GuiSlot(w, h, 0, 0, StaticGui.Image[7], false, StaticGui.AvailableCommands, StaticGui.Image[26])
                                    {
                                        MouseClick = StaticGui.ClickFunction, 
                                        MouseRightClick = StaticGui.RightClickFunction,
                                        Actions = () =>{
                                                          SoundController.playClip("move");
                                                          player.moveAhead();
                                                      },
                                        DoDragAction = StaticGui.DragAction,
                                        Father = StaticGui.AvailableCommands
                                    },
                                new GuiSlot(w, h, 0, 1, StaticGui.Image[9], false, StaticGui.AvailableCommands, StaticGui.Image[27])
                                    {
                                        MouseClick = StaticGui.ClickFunction,
                                        MouseRightClick = StaticGui.RightClickFunction,
                                        Actions = () =>{
                                                          SoundController.playClip("turn");
                                                          player.turnLeft();
                                                      },
                                        DoDragAction = StaticGui.DragAction,
                                        Father = StaticGui.AvailableCommands
                                    },
                                new GuiSlot(w, h, 0, 2, StaticGui.Image[10], false, StaticGui.AvailableCommands, StaticGui.Image[28])
                                    {
                                        MouseClick = StaticGui.ClickFunction,
                                        MouseRightClick = StaticGui.RightClickFunction,
                                        Actions = () =>
                                                      {
                                                          SoundController.playClip("turn");
                                                          player.turnRight();
                                                      },
                                        DoDragAction = StaticGui.DragAction,
                                        Father = StaticGui.AvailableCommands
                                    },
                                new GuiSlot(w, h, 0, 3, StaticGui.Image[11], false, StaticGui.AvailableCommands, StaticGui.Image[29])
                                    {
                                        MouseClick = StaticGui.ClickFunction,
                                        MouseRightClick = StaticGui.RightClickFunction,
                                        Actions =  () =>
                                                       {
                                                           SoundController.playClip("jump");
                                                           player.jumpAhead();
                                                       },
                                        DoDragAction = StaticGui.DragAction,
                                        Father = StaticGui.AvailableCommands
                                    }
                            };
            StaticGui.AvailableCommands.Slots = slots;

            #endregion

            #endregion

            #endregion

            Buttons.Add(new clsButton(Content.Load<Texture2D>(@"Buttons\main_menu_button"),
                                     Content.Load<Texture2D>(@"Buttons\main_menu_button"),
                                     new Vector2( Width - 150 , Height - 75 ), new Vector2( 125, 50),
                                     ActionsHandler.MainMenuButtonEvent));


            tipFrame.LoadContent(Content); // Carrega o conteudo do tutorial
        }
        

        public override void Update(GameTime gameTime)
        {

            //LevelCompleted();
            float difftime = gameTime.ElapsedGameTime.Milliseconds;

            if (!levelCompleteFrame.Enabled && !tipFrame.Enabled)
            {
                // Allows the game to exit
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
                   Keyboard.GetState().IsKeyDown(Keys.Escape) && StaticGui.OptionMenu != null &&
                   StaticGui.CheckTime(gameTime, StaticGui.OptionMenu.KeepClickTime))
                {
                    StaticGui.OptionMenu.IsVisible = !StaticGui.OptionMenu.IsVisible;
                    StaticGui.OptionMenu.KeepClickTime = gameTime.TotalGameTime.TotalMilliseconds;
                }

                for (int i = 0; i < _objects.Count; i++)
                {
                    Character obj = _objects.ElementAt(i);
                    obj.Update(difftime);
                    //obj.IsOutOfBounds();
                }
                //enemy.Update(difftime);
                _events.Update(difftime);
                Buttons.Update();
                StaticGui.Update(gameTime);
            }

            //_events.Update(difftime);
            

            

            levelCompleteFrame.Update(gameTime);


            tipFrame.Update(gameTime);
        }


        public override void Render(SpriteBatch renderTarget)
        {
            renderLayers(renderTarget); // Funcao para renderizar os layers na ordem correta. // Render do robo

            //renderTarget.Draw(inv, new Rectangle(0,50, 600, 11), null, Color.White);

            StaticGui.Draw(renderTarget);

            Buttons.Draw(renderTarget);
            levelCompleteFrame.Render(renderTarget);


            tipFrame.Render(renderTarget);
        }



        private void renderLayers(SpriteBatch renderTarget)
        {
            _map.Render(renderTarget); // Renderiza o Layer 1

            if (jumping) { _map.RenderUpperLayer(renderTarget); } // Se pulando, renderizar o upperLayer embaixo do player


            //enemy.Render(renderTarget);
           

            for (int i = 0; i < _objects.Count; i++)
            {
                Robot obj = (Robot)_objects.ElementAt(i);

                if(obj.isJumping()){ jumping = true; }

                obj.Render(renderTarget);
                renderTarget.Draw(Background, new Rectangle(200, 90, 90, 90), Color.White);
            }

            _events.Render(renderTarget);

             if (!jumping) _map.RenderUpperLayer(renderTarget); // se nao pulando, renderizar em cima do player.
        }



        public void SettingsFrameEvent(object sender, EventArgs e)
        {
            //busca na lista um frame com a classe correspondente a que deve ser ativada
           // _frame.Enabled = true;
        }

        public void LevelCompleted()
        {
            levelCompleteFrame.Enabled = true;
            
            
        }

        public void renderScore(float oldScore, float newScore, bool highscore)
        {
            levelCompleteFrame.setScore(oldScore, newScore, highscore);
        }


        public void CreateTipFrame()
        {
            /**
             * EEEEE  Daleeeeeeeeee xunxooooooo!!!!!!!!!
             */
            switch (ActionsHandler.level)
            {
                case 1: 
                    tipFrame = new TutorialLevel1(ActionsHandler.Game, 0, 0, Width, Height);
                    break;
                case 2:
                    tipFrame = new TutorialLevel2(ActionsHandler.Game, 0, 0, Width, Height);
                    break;
                case 3:
                    tipFrame = new TutorialLevel3(ActionsHandler.Game, 0, 0, Width, Height);
                    break;
                case 4:
                    tipFrame = new TutorialLevel4(ActionsHandler.Game, 0, 0, Width, Height);
                    break;
                case 5:
                    tipFrame = new TutorialLevel5(ActionsHandler.Game, 0, 0, Width, Height);
                    break;
                default:
                    tipFrame = new TutorialLevel5(ActionsHandler.Game, 0, 0, Width, Height); // default.. vai  ficar escondido
                    tipFrame.Enabled = false;
                    return;
            }
        }
       

    } //class
}//namespace
